// DynamicCss.cs
//

using System;
using System.Collections.Generic;
using System.Html;
using System.Runtime.CompilerServices;
using jQueryApi;

namespace Nsb
{
    [IgnoreNamespace]
    public static class DynamicCss
    {
        /// <summary>
        /// Adds the CSS rule to the DOM.
        /// Use DynamicCss.AddCssRule(ruleName, ruleDictionary).
        /// </summary>
        /// <param name="ruleName">Name of the rule in CSS standard format.</param>
        /// <param name="rules">Dictionary of the rules to add.</param>
        /// <returns></returns>
        [PreserveName]
        public static Element AddCssRule(string ruleName, Object rules)
        {
            const string dataname = "AddCssRuleData";
            jQuery jq = (jQuery)Type.GetField(Window.Self, "jQuery");
            DynamicCssData data = (DynamicCssData)Type.GetField(jq, dataname);
            if (Type.GetScriptType(data) == "undefined")
            {
                // Common closured variables
                data = (DynamicCssData)new Object();
                data.sheetName = "DynamicCss-StyleSheet";
                data.undefined_as_dictionary = (Dictionary<string, object>)Script.Literal("undefined");

                // Add static data object to jQuery
                Type.SetField(jq, dataname, data);

                // Add our private stylesheet to the DOM
                DyanmicCssNode cssNode = (DyanmicCssNode)Document.CreateElement("style");
                cssNode.id = (new Date()).GetTime().ToString();
                cssNode.type = "text/css";
                cssNode.rel = "stylesheet";
                cssNode.media = "screen";
                cssNode.title = data.sheetName;
                Document.GetElementsByTagName("head")[0].AppendChild(cssNode);
            }

            if (Type.HasField(Window.Document, "styleSheets"))
            {
                if (Type.GetScriptType(rules) == "undefined")
                {
                    DynamicStyleSheet[] stylesheets = (DynamicStyleSheet[])Type.GetField(Window.Document, "styleSheets");
                    for (int j = 0; j < stylesheets.Length; j++)
                    {
                        Element ru = null;
                        try
                        {
                            DynamicStyleSheet sth = stylesheets[j];
                            if (sth.title != data.sheetName) continue;
                            if (Type.HasMethod(sth, "insertRule"))
                            {
                                //W3C
                                int ix = sth.insertRule(ruleName + " { }", 0);
                                ru = sth.cssRules[ix];
                            }
                            else if (Type.HasMethod(sth, "addRule"))
                            { // IE<9
                                sth.addRule(ruleName, null, 0);
                                ru = sth.rules[0];
                            }
                            else
                                throw new Exception("CANT FIND insertRule OR SIMILAR CSS FUNCTION");
                        }
// ReSharper disable EmptyGeneralCatchClause
                        catch
// ReSharper restore EmptyGeneralCatchClause
                        {
                        }
                        return ru;
                    }
                    throw new Exception("FAILED TO ADD CSS RULE or NO DynamicCss SHEET");
                }
                jQuery.FromElement(AddCssRule(ruleName, data.undefined_as_dictionary)).CSS((Dictionary<string, object>)rules);
                return null;
            }
            throw new Exception("NO BROWSER DYNAMIC STYLESHEET SUPORT");
        }
    }

    public delegate int StyleInsertRule(string a, int b);
    public delegate void StyleAddRule(string a, object b, int c);

    [Imported]
    public sealed class DynamicCssData
    {
        public string sheetName = "DynamicCss-StyleSheet";
        public Dictionary<string, object> undefined_as_dictionary = (Dictionary<string, object>)Script.Literal("undefined");
    }

    [Imported]
    public sealed class DynamicStyleSheet
    {
        public string title;
        public StyleInsertRule insertRule;
        public StyleAddRule addRule;
        public Element[] rules;
        public Element[] cssRules;
        public int length;
    }

    [Imported]
    public sealed class DyanmicCssNode : Element
    {
        public string id;
        public string type;
        public string rel;
        public string media;
        public string title;
    }

}